#include "ast.h"
#include "language_scanner.h"
#include <string.h>

AST_node* ast_malloc_node(AST_node_op op,AST_assoc_type assoc,AST_node_type type) {
	AST_node* r;
	r = malloc(sizeof(AST_node));
	if(!r) {
		return NULL;
	}
	r->op = op;
	r->assoc = assoc;
	r->type = type;
	r->ancestors_len = 0;
	r->children_len = 0;
	r->ancestors = NULL;
	r->children = NULL;

	return r;
}

AST_node* ast_dup_node(AST_node *node) {
	AST_node *r;
	r = malloc(sizeof(AST_node));
	return NULL == r ? NULL : memcpy(r,node,sizeof(AST_node)); 
}
int ast_push_ancestor(AST_node *node,AST_node *ancestor) {
	if(!node->ancestors_len) {
		node->ancestors = malloc(sizeof(AST_node*));
		if(!node->ancestors) {
			return 0;
		}
	}
	else {
		node->ancestors = realloc(node->ancestors,sizeof(AST_node*)*(node->ancestors_len+1));
		if(!node->ancestors) {
			return 0;
		}
	}
	node->ancestors[node->ancestors_len] = ancestor;
	return ++node->ancestors_len;
}
AST_node* ast_pop_ancestor(AST_node *node) {
	AST_node *r=NULL;
	if(node->ancestors_len) {
		node->ancestors_len--;
		r = node->ancestors[node->ancestors_len];
		node->ancestors = realloc(node->ancestors,sizeof(AST_node*)*(node->ancestors_len));
	}
	return r;
}
int ast_add_child(AST_node *node,AST_node *child) {
	if(!node->children_len) {
		node->children = malloc(sizeof(AST_node*));
		if(!node->children) {
			return 0;
		}
	}
	else {
		node->children = realloc(node->children,sizeof(AST_node*)*(node->children_len+1));
		if(!node->children) {
			return 0;
		}
	}
	node->children[node->children_len] = child;
	return ++node->children_len;
}

int ast_free_node(AST_node *node) {
	size_t i;
	for(i=0;i<node->children_len;i++) {
		ast_free_node(node->children[i]);
	}
	switch(node->type) {
		case root:
			//TODO: free hash table, LATER: call destructors, etc
			free(node->val.root.filename);
		case unary:
			//TODO: fix label
			if(node->val.unary.val->type == LABEL) {
				free(node->val.unary.val->val.str.val);
			}
			free(node->val.unary.val);
			break;
		case binary:
			if(right == node->assoc) {
				ast_free_node(node->val.binary.right);
				ast_free_node(node->val.binary.left);
			}
			else {
				ast_free_node(node->val.binary.left);
				ast_free_node(node->val.binary.right);
			}
			break;
		case chain:
			ast_free_node(node->val.chain.val);
			break;
	}
	free(node);
	return 0;
}
char* ast_serialize_node(AST_node *node) {
	size_t i;
	char *r;
	char *r2;
	char *fmt;
	int ret;
	switch(node->type) {
		case root:
			//TODO: free hash table, LATER: call destructors, etc
			switch(node->op) {
				case top:
					break;
				default:
					break;
			}
		case unary:
			switch(node->op) {
				case double_const:
					break;
				case integer_const:
					break;
				case label:
					//free(node->val.unary.val->val.str.val);
					break;
				case print:
					break;
				default:
					break;
			}

			break;
		case binary:
			switch(node->op) {
				case add:
					break;
				case sub:
					break;
				case mul:
					break;
				case divide:
					break;
				case assignment:
					break;
				default:
					break;
			}
			break;
		case chain:
			switch(node->op) {
				case math_expr:
					break;
				default:
					break;
			}
			break;
		default:
			break;
	}
	/*
	for(i=0;i<node->children_len;i++) {
		r2 = ast_serialize_node(node->children[i]);
		ret = asprintf(&r,"%ld: %s ",r2);
		if(!r) {
			r = NULL;
			break;
		}
	}
	*/
	return r;
}
